package org.budo.support.config.processor;

import java.io.File;
import java.io.InputStream;
import java.util.Properties;

import org.budo.support.lang.util.FileUtil;
import org.budo.support.lang.util.IoUtil;
import org.budo.support.lang.util.PropertiesUtil;
import org.budo.support.slf4j.Slf4j;
import org.budo.time.Time;
import org.slf4j.Logger;
import org.springframework.beans.factory.BeanFactory;

/**
 * @author lmw
 */
public class AbstractBudoConfigProcessor {
    private static final Logger log = Slf4j.getLogger();

    private Properties properties;

    private BeanFactory beanFactory;

    /**
     * 如果直接实例化这个类，就打警告日志
     */
    public AbstractBudoConfigProcessor() {
        if (this.getClass().equals(AbstractBudoConfigProcessor.class)) {
            log.warn("#30 you are using AbstractBudoConfigProcessor? and not extends?");
        } else {
            log.info("#32 using AbstractBudoConfigProcessor, this.type=" + this.getClass() + ", this=" + this);
        }
    }

    public Properties getProperties() {
        if (null != this.properties) {
            return this.properties;
        }

        synchronized (AbstractBudoConfigProcessor.class) {
            if (null != this.properties) {
                return this.properties;
            }

            return this.properties = this.loadProperties();
        }
    }

    private Properties loadProperties() {
        String buildConfPath = null;
        String buildConfPath_1 = FileUtil.getCodeSourceLocation(this.getClass()).replace("/lib/", "/conf/") + "budo.build.conf.properties";
        String buildConfPath_2 = FileUtil.getCodeSourceLocation(this.getClass()).replace("/lib/", "/classes/") + "budo.build.conf.properties";

        if (FileUtil.exists(buildConfPath_1)) {
            buildConfPath = buildConfPath_1;
        } else if (FileUtil.exists(buildConfPath_2)) {
            buildConfPath = buildConfPath_2;
        }

        if (!FileUtil.exists(buildConfPath)) {
            return this.fileNotExistsProperties(buildConfPath, buildConfPath_1, buildConfPath_2);
        }

        return this.readFileProperties(buildConfPath);
    }

    private Properties readFileProperties(String buildConfPath) {
        InputStream inputStream = IoUtil.fileInputStream(buildConfPath);

        Properties properties = new Properties();
        properties.put("BudoConfigProcessor.type", this.getClass().getName()); // 数据加载时间
        properties.put("BudoConfigProcessor.loadAt", Time.now().toString("yyyy-MM-dd HH:mm:ss.SSS")); // 数据加载时间
        properties.put("BudoConfigProcessor.File.lastModifiedAt", Time.when(new File(buildConfPath).lastModified()).toString("yyyy-MM-dd HH:mm:ss.SSS")); // 文件更新时间

        PropertiesUtil.load(properties, inputStream); // 读取文件内容

        log.info("#78 loadProperties, properties=" + properties //
                + ", buildConfPath=" + buildConfPath //
                + ", canonicalPath=" + FileUtil.getCanonicalPath(new File(buildConfPath)));
        return properties;
    }

    private Properties fileNotExistsProperties(String buildConfPath, String buildConfPath_1, String buildConfPath_2) {
        String canonicalPath1 = FileUtil.getCanonicalPath(new File(buildConfPath_1));
        String canonicalPath2 = FileUtil.getCanonicalPath(new File(buildConfPath_2));

        log.error("#88 buildConfPath=" + buildConfPath //
                + ", buildConfPath_1=" + buildConfPath_1 //
                + ", buildConfPath_1.canonicalPath=" + canonicalPath1//
                + ", buildConfPath_2=" + buildConfPath_2 //
                + ", buildConfPath_2.canonicalPath=" + canonicalPath2);

        Properties properties = new Properties();
        properties.put("BudoConfigProcessor.buildConfPath1.notFound", buildConfPath_1);
        properties.put("BudoConfigProcessor.buildConfPath2.notFound", buildConfPath_2);

        properties.put("BudoConfigProcessor.type", this.getClass().getName()); // 数据加载时间
        properties.put("BudoConfigProcessor.loadAt", Time.now().toString("yyyy-MM-dd HH:mm:ss.SSS")); // 数据加载时间
        return properties;
    }

    public BeanFactory getBeanFactory() {
        return this.beanFactory;
    }

    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }
}